package com.fudan.adse.service.impl;

import cn.hutool.core.text.CharSequenceUtil;
import com.fudan.adse.api.CommonResult;
import com.fudan.adse.api.ResultCode;
import com.fudan.adse.component.GrpcServiceStub;
import com.fudan.adse.dao.UserRoleDao;
import com.fudan.adse.domain.bo.OAuthTokenBO;
import com.fudan.adse.domain.dto.UserParam;
import com.fudan.adse.domain.po.Role;
import com.fudan.adse.domain.po.User;
import com.fudan.adse.domain.po.UserExample;
import com.fudan.adse.domain.po.UserRole;
import com.fudan.adse.domain.vo.UserVO;
import com.fudan.adse.exception.ApiException;
import com.fudan.adse.exception.Asserts;
import com.fudan.adse.mbg.mapper.UserMapper;
import com.fudan.adse.mbg.mapper.UserRoleMapper;
import com.fudan.adse.service.AuthService;
import com.fudan.adse.service.UserService;
import com.fudan.adse.utils.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;


/**
 * @author Jerry Zhang <zhangjian16@fudan.edu.cn>
 * @desc UserService实现类
 * @date 2022-09-14 12:03
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {
    private GrpcServiceStub grpcServiceStub;
    private AuthService authService;
    private UserMapper userMapper;

    private UserRoleDao userRoleDao;

    private UserRoleMapper userRoleMapper;

    @Override
    public String addUser(UserParam param) {
        log.info("开始新增用户");
        User user = new User();
        BeanUtils.copyProperties(param, user);
        user.setUsername(UUIDUtil.generateUUID(user.toString()));
        user.setRegisterTime(new Date());
        user.setStatus(true);
        log.info("加密密码");
        user.setPassword(passwordEncoder2().encode(user.getPassword()));
        log.info("新用户的 uuid 为 {}", user.getUsername());
        int res = userMapper.insert(user);
        if (res > 0) {
            UserRole userRole = new UserRole();
            userRole.setUserId(user.getId());
            userRole.setRoleId(4);
            userRole.setStatus(true);
            userRoleMapper.insert(userRole);
            log.info("新用户 {} ({}) 添加成功！", user.getNickName(), user.getUsername());
            return user.getUsername();
        } else {
            log.info("新用户 {} 添加失败！", user.getNickName());
            Asserts.fail("新用户" + user.getNickName() + "添加失败");
        }
        return null;
    }


    @Override
    public CommonResult login(String username, String password) {
        if (CharSequenceUtil.isEmpty(username) || CharSequenceUtil.isEmpty(password)) {
            Asserts.fail("用户名或密码不能为空！");
        }
        Map<String, String> params = new HashMap<>();
        params.put("grant_type", "password");
        params.put("client_id", "admin");
        params.put("client_secret", "admin");
        params.put("username", username);
        params.put("password", password);
        CommonResult restResult = authService.getAccessToken(params);
        if (ResultCode.SUCCESS.getCode() == restResult.getCode() && restResult.getData() != null) {
            // todo 更新登录时间
        }
        return restResult;
    }

    @Override
    public UserVO getUserByUsername(String username) throws ApiException {
        UserVO ret = new UserVO();
        loadUserByUsername(username, ret);
        return ret;
    }

    private <N> void loadUserByUsername(String username, N typeClass) {
        UserExample example = new UserExample();
        example.createCriteria().andUsernameEqualTo(username);
        List<User> users = userMapper.selectByExample(example);
        if (users == null || users.isEmpty()) {
            Asserts.fail("username 不存在");
        } else {
            BeanUtils.copyProperties(users.get(0), typeClass);
        }
    }

    @Override
    public List<UserVO> getAllUsers() {
        UserExample userExample = new UserExample();
        userExample.createCriteria();
        List<User> users = userMapper.selectByExample(userExample);
        List<UserVO> retList = new ArrayList<>();
        for (User user : users) {
            UserVO ret = new UserVO();
            BeanUtils.copyProperties(user, ret);
            retList.add(ret);
        }
        return retList;
    }

    @Override
    public void updateUser(User user) throws ApiException {
        String username = user.getUsername();
        checkUuid(username);
        UserExample example = new UserExample();
        example.createCriteria().andUsernameEqualTo(username);
        if (userMapper.updateByExampleSelective(user, example) < 0) {
            throw new ApiException("更新用户信息失败");
        }
    }


    @Override
    public void deleteUser(String username) throws ApiException {
        checkUuid(username);
        UserExample userExample = new UserExample();
        userExample.createCriteria().andUsernameEqualTo(username);
        if (userMapper.deleteByExample(userExample) < 0) {
            throw new ApiException("更新用户信息失败");
        }
    }

    private void checkUuid(String uuid) {
        if (CharSequenceUtil.isEmpty(uuid)) {
            Asserts.fail("username 不能为空");
        } else if (getUserByUsername(uuid) == null) {
            Asserts.fail("username 不存在");
        }
    }

    @Override
    public List<Role> getRoleList(Integer userId) {
        return userRoleDao.getRoleList(userId);
    }

    public PasswordEncoder passwordEncoder2() {
        return new BCryptPasswordEncoder();
    }


    @Autowired
    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }


    @Autowired
    public void setUserRoleDao(UserRoleDao userRoleDao) {
        this.userRoleDao = userRoleDao;
    }

    @Autowired
    public void setUserRoleMapper(UserRoleMapper userRoleMapper) {
        this.userRoleMapper = userRoleMapper;
    }

    @Autowired
    public void setGrpcServiceStub(GrpcServiceStub grpcServiceStub) {
        this.grpcServiceStub = grpcServiceStub;
    }

    @Autowired
    public void setAuthService(AuthService authService) {
        this.authService = authService;
    }
}
